package org.xml.create.DOM;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.Book;
import org.xml.sax.SAXException;

/**
 * 该类使用DOM方式生成books_dom.xml
 */
public class DOMTest {

	public static void main(String[] args) throws ParserConfigurationException,
			TransformerException, SAXException, IOException {
		newXMLByDOM();//一个个手工创建节点，添加属性
		newXMLByDOM2();//通过解析XML文件后存储在ArrayList中的对象创建XML
	}

	//通过手工创建节点
	private static void newXMLByDOM() throws ParserConfigurationException,
			TransformerException, SAXException, IOException {
		// 1.创建一个DocumentBuilderFactory对象
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		// 2.根据DocumentBuilderFactory对象创建一个DocumentBuilder对象
		DocumentBuilder db = dbf.newDocumentBuilder();

		// 3.使用DocumentBuilder对象的newDocument（）方法创建一个新的Document对象（DOM树）
		Document document = db.parse("books1.xml");
		document.setXmlStandalone(true);// 设置XML文件的声明standalone的值为yes并不予显示
//
//		// 4.为DOM树增加节点
//		Element bookStore = document.createElement("bookstore");
//		Element book = document.createElement("book");
//		book.setAttribute("id", "1");// 设置book的id属性为1
//		Element name = document.createElement("name");
//		name.setTextContent("冰与火之歌");
//		Element author = document.createElement("author");
//		author.setTextContent("乔治马丁");
//
//		Element year = document.createElement("year");
//		Text yearText = document.createTextNode("2014");// 创建一个文本节点
//		year.appendChild(yearText);// 为元素节点添加子节点（文本节点）
//
//		Element price = document.createElement("price");
//		price.setTextContent("89");
//
//		book.appendChild(name);
//		book.appendChild(author);
//		book.appendChild(year);
//		book.appendChild(price);
//		bookStore.appendChild(book);// 将book节点添加到bookstore中
//
//		book = document.createElement("book");
//		Attr bookAttr = document.createAttribute("id");// 创建一个名为id的属性节点
//		bookAttr.setNodeValue("2");// 为id属性节点设置id属性值
//		book.setAttributeNode(bookAttr);// 为元素节点book设置属性节点
//		name = document.createElement("name");
//		name.setTextContent("安徒生童话");
//		year = document.createElement("year");
//		year.setTextContent("2004");
//		price = document.createElement("price");
//		price.setTextContent("77");
//		Element language = document.createElement("language");
//		language.setTextContent("English");
//		book.appendChild(year);
//		book.insertBefore(name, year);// 在year节点之前插入name节点
//		book.appendChild(price);
//		book.appendChild(language);
//		bookStore.appendChild(book);
//		document.appendChild(bookStore);// 将bookstore（已经包含了book节点）节点添加到DOM树中

		Node book =  document.getElementsByTagName("book").item(0);
		Element language = document.createElement("language");
		language.setTextContent("简体中文");
		book.appendChild(language);
		// 5.创建一个TransformerFactory对象
		TransformerFactory tff = TransformerFactory.newInstance();
		// 6.通过TransformerFactory对象创建一个Transformer对象
		Transformer tf = tff.newTransformer();

		// 7.利用Transformer对象的transform方法指定输出流
		tf.setOutputProperty(OutputKeys.INDENT, "yes");// 设置缩进、换行
		tf.transform(new DOMSource(document), new StreamResult(new File(
				"books_append_dom.xml")));
	}

	//通过存储在ArrayList中的Book对象自动生成XML
	private static void newXMLByDOM2() throws ParserConfigurationException,
			TransformerFactoryConfigurationError, TransformerException {
		ArrayList<Book> bookList = domParser();
		DocumentBuilder db = DocumentBuilderFactory.newInstance()
				.newDocumentBuilder();
		Document document = db.newDocument();
		Element bookStore = document.createElement("bookstore");
		for (Book bookEntity : bookList) {
			Element book = document.createElement("book");
			if (bookEntity.getId() != null
					&& !bookEntity.getId().trim().equals("")) {
				book.setAttribute("id", bookEntity.getId());
			}
			if (bookEntity.getName() != null
					&& !bookEntity.getName().trim().equals("")) {
				Element name = document.createElement("name");
				name.setTextContent(bookEntity.getName());
				book.appendChild(name);
			}
			if (bookEntity.getAuthor() != null
					&& !bookEntity.getAuthor().trim().equals("")) {
				Element author = document.createElement("author");
				author.setTextContent(bookEntity.getAuthor());
				book.appendChild(author);
			}
			if (bookEntity.getYear() != null
					&& !bookEntity.getYear().trim().equals("")) {
				Element year = document.createElement("year");
				year.setTextContent(bookEntity.getYear());
				book.appendChild(year);
			}
			if (bookEntity.getPrice() != null
					&& !bookEntity.getPrice().trim().equals("")) {
				Element price = document.createElement("price");
				price.setTextContent(bookEntity.getPrice());
				book.appendChild(price);
			}
			if (bookEntity.getLanguage() != null
					&& !bookEntity.getLanguage().trim().equals("")) {
				Element language = document.createElement("language");
				language.setTextContent(bookEntity.getLanguage());
				book.appendChild(language);
			}
			bookStore.appendChild(book);
		}
		document.appendChild(bookStore);
		Transformer tf = TransformerFactory.newInstance().newTransformer();
		tf.setOutputProperty(OutputKeys.INDENT, "yes");
		tf.setOutputProperty(OutputKeys.ENCODING, "unicode");
		tf.transform(new DOMSource(document), new StreamResult(new File(
				"books_dom2.xml")));
	}

	public static ArrayList<Book> domParser() {
		Book book = null;
		ArrayList<Book> books = new ArrayList<Book>();
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document document = db.parse("books1.xml");
			NodeList bookList = document.getElementsByTagName("book");// 获取所有的book节点的集合
			// 遍历每一个book节点
			for (int i = 0; i < bookList.getLength(); i++) {
				book = new Book();// 每遇到一个book节点就创建一个book对象
				Node bookNode = (Node) bookList.item(i);// 通过item（i）方法获取一个book节点
				NamedNodeMap attributes = bookNode.getAttributes();// 获取book节点的属性集合

				// 遍历book节点的属性
				for (int j = 0; j < attributes.getLength(); j++) {
					Node attribute = attributes.item(j);// 通过item（index）方法获取NamedNodeMap中的某个属性
					if ("id".equals(attribute.getNodeName())) {
						book.setId(attribute.getNodeValue());
					}
				}

				// 解析book节点的子节点
				NodeList childNodes = bookNode.getChildNodes();
				// 遍历childNodes获取每个节点的节点名和节点值
				for (int j = 0; j < childNodes.getLength(); j++) {
					// 区分textNode和elementNode
					if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE) {
						if ("name".equals(childNodes.item(j).getNodeName())) {
							book.setName(childNodes.item(j).getFirstChild()
									.getNodeValue());
						} else if ("author".equals(childNodes.item(j)
								.getNodeName())) {
							book.setAuthor(childNodes.item(j).getTextContent());
						} else if ("year".equals(childNodes.item(j)
								.getNodeName())) {
							book.setYear(childNodes.item(j).getTextContent());
						} else if ("price".equals(childNodes.item(j)
								.getNodeName())) {
							book.setPrice(childNodes.item(j).getTextContent());
						} else if ("language".equals(childNodes.item(j)
								.getNodeName())) {
							book.setLanguage(childNodes.item(j)
									.getTextContent());
						}
					}
				}
				books.add(book);// 结束一本书的遍历的时候将其加入ArrayList中
			}
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return books;
	}
}
